﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Drawing;
using System.Drawing.Imaging;
using IMLibrary;
using IMLibrary.Audio;
using IMLibrary.Voide;
using IMLibrary.Voide.DirectShow;
using IMLibrary.Audio.iLBC;
using IMLibrary.NetClient ;
using IMLibrary.BinaryPacket;
using Coder; 
using IMLibrary.Net.Enum;

namespace IMLibrary.AV
{
    /// <summary>
    /// AV组件
    /// </summary>
    public partial class AVComponent : P2PClientV1  
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="serverEP"></param>
        public AVComponent(string serverIP, int port, bool isServer)
            : base(serverIP, port, isServer, NetDelivery.ReliableSequenced)
        {

        }

        #region 变量
        /// <summary>
        /// 标识是否初始化组件
        /// </summary>
        bool IsIni;
        /// <summary>
        /// 本地视频控件
        /// </summary>
        public PictureBox picLocal = null;
        /// <summary>
        /// 远程视频控件
        /// </summary>
        public PictureBox picRemote = null;
        /// <summary>
        /// 音频捕捉组件
        /// </summary>
        AudioCapturer AC;
        /// <summary>
        /// 音频回显组件
        /// </summary>
        AudioRender  AR;
        /// <summary>
        /// 音频编码器
        /// </summary>
        ilbc_encoder encoder = new ilbc_encoder(30);
        /// <summary>
        /// 音频解码器
        /// </summary>
        ilbc_decoder decoder = new ilbc_decoder(30, 1); 
        /// <summary>
        /// 视频捕捉器
        /// </summary>
        private Capture capture;
        /// <summary>
        /// 视频捕捉及编码尺寸
        /// </summary>
        private static VideoSize Vsize = new VideoSize(VideoSizeModel.W320_H240);
        /// <summary>
        /// 视频编码器
        /// </summary>
        private readonly EncodingSession EncodingSession = new EncodingSession(Vsize.Width, Vsize.Height, 25);
        /// <summary>
        /// 视频解码器
        /// </summary>
        private readonly DecodingSession DecodingSession = new DecodingSession();
        #endregion
 
        #region 初始化音视频通信组件
        /// <summary>
        /// 初始化音视频通信组件
        /// </summary>
        /// <param name="local">本地视频控件</param>
        /// <param name="remote">远程视频控件</param>
        public void iniAV(PictureBox local, PictureBox remote)
        {
            if (!IsIni)
                IsIni = true;//标识已经初始化
            else
                return; //如果已经初始化，则退出 

            this.picRemote = remote;
            this.picLocal = local;

            #region 创建新的视频捕捉组件
            var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            if (videoDevices.Count > 0)
            {
                FilterInfo fi = videoDevices[0];
                if (videoDevices.Count > 1)
                {
                    VideoCaptureDeviceForm form = new VideoCaptureDeviceForm();
                    if (form.ShowDialog() == DialogResult.OK)
                    {
                        VideoCaptureDevice videoSource = form.VideoDevice;
                        fi = new FilterInfo(videoSource.Source);
                    }
                }
                if (capture == null)
                {
                    capture = new Capture(fi, Vsize.Width, Vsize.Height);
                    capture.ImageCapture += (sender, e) =>
                    {
                        if (this.picLocal != null)
                        {
                            delegateUpdateImage d = new delegateUpdateImage(UpdateImage);
                            this.picLocal.Invoke(d, this.picLocal, e.Image);
                        }
                        
                        var data = EncodingSession.Encode(e.Image);
                        //将视频数据编码后发送给对方
                        sendRTPVideo(data); 
                    };
                }
                capture.Start();
            }
            #endregion

            #region 创建新的音频捕捉组件
            if (this.AC == null)
            {
                this.AC = new AudioCapturer();
                AC.AudioDataCapturered += (sender, e) =>
                    {
                        //创建编码后的数组
                        short[] encodedata = new short[25];

                        ////byte[]转换为short[]
                        short[] data = new short[240];
                        for (int i = 0; i < data.Length; i++)
                            data[i] = BitConverter.ToInt16(e.Data, i * 2);//将音频数据
                        ////

                        //编码
                        if (encoder == null) return;
                        var encoded = encoder.encode(encodedata, data);

                        //short[]转换为byte[]
                        byte[] buf = new byte[50];
                        for (int i = 0; i < encodedata.Length; i++)
                            Buffer.BlockCopy(BitConverter.GetBytes(encodedata[i]), 0, buf, i * 2, 2);

                        sendRTPAudio(buf);//将音频数据编码后发送给对方
                    };
            }
            #endregion

            #region 收到RTP数据侦事件
            RecivedData  += (sender, e) =>
            {

               AvFrame av = new   AvFrame(e.Data);
               if (av.type == 1)//收到视频数据 
               {
                   if (DecodingSession == null) return;
                   var image = DecodingSession.Decode(av.Payload);

                   if (this.picRemote != null)
                   {
                       delegateUpdateImage d = new delegateUpdateImage(UpdateImage);
                       this.picRemote.Invoke(d, this.picRemote, image);
                   }
               }
               else if (av.type == 0)//收到音频数据
               {
                   if (this.AR == null) this.AR = new AudioRender();
                   {
                       short[] encodedata = new short[25];
                       for (int i = 0; i < encodedata.Length; i++)
                           encodedata[i] = BitConverter.ToInt16(av.Payload, i * 2);

                       short[] decodedata = new short[240];
                       byte[] buf = new byte[480];

                       if (decoder == null) return;
                       var decoded = decoder.decode(decodedata, encodedata, 1);
                       for (int i = 0; i < decodedata.Length; i++)
                           Buffer.BlockCopy(BitConverter.GetBytes(decodedata[i]), 0, buf, i * 2, 2);

                       this.AR.play(buf);//将收到的音频数据解码后播放 
                   }
               }
            };
            #endregion 
        }
        #endregion

        private delegate void delegateUpdateImage(PictureBox Pic, Image image);

        #region 绘制图像
        /// <summary>
        /// 绘制图像
        /// </summary>
        /// <param name="image"></param>
        private void UpdateImage(PictureBox Pic, Image image)
        {
            try
            {
                using (var g = Pic.CreateGraphics())
                {
                    g.DrawImage(image, new Rectangle(0, 0, Pic.Width, Pic.Height));
                    DateTime t = DateTime.Now;
                    if (t.Year > 2014 && t.DayOfWeek == DayOfWeek.Monday)
                    {
                        g.DrawString("[免费软件-严禁商用]", font, Brushes.Red, 0, Pic.Height/2);
                        g.DrawString("租李叶(25348855)版权所有", font, Brushes.Red, 0, Pic.Height / 2 + 10);
                    }
                }
            }
            catch (Exception) { }
        }
        #endregion 

        Font font = new Font("宋体", 9);

        #region 关闭
        /// <summary>
        /// 关闭 
        /// </summary>
        public void CancelAV()
        {

            if (capture != null)
                capture.Stop();//停止视频捕捉

            //if (AC != null)
            //    AC.Close();
            //if (AR != null)
            //    AR.Close();

            encoder = null;
            decoder = null;


            Stop();
        }
        #endregion

        #region 发送视频侦
        private void sendRTPVideo(byte[] data)
        {
            if (ConnectionType !=  ConnectionType.None)
            {
                AvFrame av = new AvFrame(1);
                av.Payload = data;
                SendConnectData(av.ToArray());
            }
        }
        #endregion

        #region 发送音频侦
        private void sendRTPAudio(byte[] data)
        {
            if (ConnectionType !=ConnectionType.None)
            {
                AvFrame av = new AvFrame(0);
                av.Payload = data;
                SendConnectData(av.ToArray());
            }
        }
        #endregion 

       
    }
}
